class GameScene extends eui.Component implements  eui.UIComponent {
	
	// 游戏场景组
	public blockPanel:eui.Group;
	// 游戏场景中的积分
	public scoreLabel:eui.Label;
	// 小 i
	public player:eui.Image;

	/**************************工厂设计模式*****************************/

	// 所有方块资源的数组
	private blockSourceNames: Array<string> = [];
	// 所有方块的数组
	private blockArr: Array<eui.Image> = [];
	// 所有回收方块的数组
	private reBackBlockArr: Array<eui.Image> = [];

	/**************************音频*****************************/

	// 按下的音频
	private pushVoice: egret.Sound;
	// 弹跳的音频
	private jumpVoice: egret.Sound;


	/**********************************************************/

	// 判断是否按下状态
	private isReadyJump = false;

	// 按下音频的 SoundChannel 对象
	private pushSoundChannel: egret.SoundChannel;

	// 随机盒子距离跳台的距离
	private minDistance = 240;
	private maxDistance = 400;
	// 跳跃的距离
	public jumpDistance: number = 0;

	// 游戏中得分
	private score = 0;

	// 当前的盒子（最新出现的盒子）
	private currentBlock: eui.Image;

	// 下一个盒子方向（1 靠右侧出现 / -1 靠左侧出现）
	public direction: number = 1;

	// tanθ 角度值
	public tanAngle: number = 0.55604719640118;

	// 落脚点
	private targetPos: egret.Point;

	// 左侧跳跃点
	private leftOrigin = {"x": 180, "y": 350};
	// 右侧跳跃点
	private rightOrigin = {"x": 505, "y": 350};

	/********************************游戏结束界面***********************/
	// 游戏结束界面容器
	public overPanel:eui.Group;
	// 分数显示
	public overScoreLabel:eui.Label;
	// 再来一局
	public restartBtn:eui.Button;
	/*************************************************************/


	public constructor() {
		super();
	}

	protected partAdded(partName:string,instance:any):void
	{
		super.partAdded(partName,instance);
	}


	protected childrenCreated():void
	{
		super.childrenCreated();
		this.init();
		this.reset();
	}

	/**
	 * 初始化
	 */
	private init() {
		this.blockSourceNames = ['block1_png','block2_png','block3_png'];

		// 初始化音频
		this.pushVoice = RES.getRes('push_mp3');
		this.jumpVoice = RES.getRes('jump_mp3');

		// 打开 touchEnabled 属性
		this.blockPanel.touchEnabled = true;
		this.blockPanel.addEventListener(
			egret.TouchEvent.TOUCH_TAP,
			this.onKeyDown,
			this
		);
		this.blockPanel.addEventListener(
			egret.TouchEvent.TOUCH_END,
			this.onKeyUp,
			this
		);

		// 绑定结束按钮
		this.restartBtn.addEventListener(
			egret.TouchEvent.TOUCH_TAP,
			this.restartHandler,
			this
		);

		// 设置玩家锚点
		this.player.anchorOffsetX = this.player.width / 2;
		this.player.anchorOffsetY = this.player.height - 20;

		// 心跳计时器
		egret.Ticker.getInstance().register(function(dt){
			dt /= 1000;
			if(this.isReadyJump) {
				this.jumpDistance += 300 * dt;
			}
		}, this)

	}

	/**
	 * 按下的事件逻辑
	 */
	private onKeyDown() {
		// 播放按下的音频
		this.pushSoundChannel = this.pushVoice.play(0,1);
		// 变形
		egret.Tween.get(this.player).to({
			scaleY: 0.5
		}, 3000);

		this.isReadyJump = true;
	}

	/**
	 * 放开的事件逻辑
	 */
	private onKeyUp() {
		// 判断是否在按下状态
		if(!this.isReadyJump) {
			return;
		}

		// 声明落脚点坐标
		if(!this.targetPos) {
			this.targetPos = new egret.Point();
		}

		// 立即让屏幕不可点，等小人落下后重新可点
		this.blockPanel.touchEnabled = false;
		
		// 停止播放按压音频，并且播放跳跃音频
		this.pushSoundChannel.stop();
		this.jumpVoice.play(0,1);

		// 清除所有动画
		egret.Tween.removeAllTweens();
		this.blockPanel.addChild(this.player);

		// 结束跳跃状态
		this.isReadyJump = false;

		// 落脚点坐标
		this.targetPos.x = this.player.x + this.jumpDistance * this.direction;
		// 根据落点重新计算斜率，确保小人往目标中心跳跃
		this.targetPos.y = this.player.y + this.jumpDistance * (this.currentBlock.y - this.player.y)/(this.currentBlock.x - this.player.x) * this.direction;
		
		// 执行跳跃动画
		egret.Tween.get(this).to({factor: 1}, 500).call(() => {
			this.player.scaleY = 1;
			this.jumpDistance = 0;
			// 判断是否跳跃成功
			this.judgeResult();
		});

		// 执行小人空翻动画
		this.player.anchorOffsetY = this.player.height / 2;
		egret.Tween.get(this.player).to({rotation: this.direction > 0 ? 360 : -360}, 200).call(() => {
			this.player.rotation = 0;
		}).call(() => {
			this.player.anchorOffsetY = this.player.height - 20;
		});
	}

	/**
	 * 工厂方法，创建一个方块
	 */
	private createBlock(): eui.Image {
		// 定义一个方块盒子
		var blockNode: eui.Image = null;
		if(this.reBackBlockArr.length) {
			// 回收池里有，则直接取
			blockNode = this.reBackBlockArr.splice(0,1)[0];
		}else {
			// 回收池里面没有，则重新创建
			blockNode = new eui.Image();
		}
		// 使用随机背景
		let n = Math.floor(Math.random() * this.blockSourceNames.length);
		console.log('-----------------------' + n);
		blockNode.source = this.blockSourceNames[n];
		this.blockPanel.addChild(blockNode);

		// 设置方块的锚点
		blockNode.anchorOffsetX = 222;
		blockNode. anchorOffsetY = 78;
		// 把新建的 block 添加进入 blockArr 里
		this.blockArr.push(blockNode);

		return blockNode;
	}


	// 重置游戏
	public reset() {
		this.overPanel.visible = false;
		// 清空舞台
		this.blockPanel.removeChildren();
		this.blockArr = [];

		// 添加一个方块
		let blockNode = this.createBlock();
		blockNode.touchEnabled = false;

		// 设置方块的起始位置
		blockNode.x = 200;
		blockNode.y = this.height / 2 + blockNode.height;

		this.currentBlock = blockNode;

		// 摆正小人的位置
		this.player.x = this.currentBlock.x;
		this.player.y = this.currentBlock.y;
		this.blockPanel.addChild(this.player);

		// 添加积分
		this.blockPanel.addChild(this.scoreLabel);

		// 重置分数
		this.score = 0;
		this.scoreLabel.text = this.score.toString();

		// 重置盒子方向
		this.direction = 1;

		// 添加下一块方块
		this.addBlock();

	}

	/**
	 * 添加一个方块
	 */
	private addBlock() {
		// 随机一个方块
		let blockNode = this.createBlock();
		// 设置位置
		let distance = this.minDistance + Math.random()*(this.maxDistance - this.minDistance);
		
		if(this.direction > 0) {
			blockNode.x = this.currentBlock.x + distance;
			blockNode.y = this.currentBlock.y - distance*this.tanAngle;
		}else {
			blockNode.x = this.currentBlock.x - distance;
			blockNode.y = this.currentBlock.y - distance*this.tanAngle;
		}
		this.currentBlock = blockNode;
	}

	// 根据 this.jumpDistance 来判断跳跃是否成功
	private judgeResult(){
		if(Math.pow(this.currentBlock.x - this.player.x, 2) + Math.pow(this.currentBlock.y - this.player.y, 2) <= 70*70) {
			// 跳跃成功
			// 更新积分
			this.score++;
			this.scoreLabel.text = this.score.toString();

			// 随机下一个方块出现的位置
			this.direction = Math.random() > 0.5 ? 1 : -1;

			// 当前方块要移到相应的跳跃点的距离
			var blockX, blockY;
			blockX = this.direction > 0 ? this.leftOrigin.x : this.rightOrigin.x;
			blockY = this.height / 2 + this.currentBlock.height;

			// 小人要移动到的点
			var playerX, playerY;
			playerX = this.player.x - (this.currentBlock.x - blockX);
			playerY = this.player.y - (this.currentBlock.y - blockY);

			// 更新页面的位置
			this.update(this.currentBlock.x - blockX, this.currentBlock.y - blockY);

			// 更新小人的位置
			egret.Tween.get(this.player).to({
				x: playerX,
				y: playerY
			}, 1000).call(() => {
				// 开始创建下一块方块
				this.addBlock();
				// 让屏幕重新可点
				this.blockPanel.touchEnabled = true;
			})

			console.log("x" + this.currentBlock.x);

		}else {
			// 跳跃失败
			console.log("游戏失败！");
			this.overPanel.visible = true;
			this.overScoreLabel.text = this.score.toString();
		}
	}

	// 更新页面
	private update(x, y) {
		egret.Tween.removeAllTweens();
		for(var i: number = this.blockArr.length - 1; i >= 0; i--) {
			var blockNode = this.blockArr[i];
			if(blockNode.x + (blockNode.width - 222) < 0 || blockNode.x - 222 > this.width || blockNode.y - 78 > this.height) {
				// 方块超出屏幕，从显示列表中移除
				this.blockPanel.removeChild(blockNode);
				this.blockArr.splice(i,1);
				// 添加到回收数组中
				this.reBackBlockArr.push(blockNode);
			}else {
				// 没有超出屏幕的范围，则移动
				egret.Tween.get(blockNode).to({
					x: blockNode.x - x,
					y: blockNode.y - y
				}, 1000)
			}
		}
	}

	// 重新一局游戏
	private restartHandler(){
		this.reset();
		// 游戏场景可点
		this.blockPanel.touchEnabled = true;
	}

	// 添加 factor 的 set，get 方法，注意使用 public 
	public get factor(): number {
		return 0;
	}

	// 计算方法参考，二次贝塞尔曲线公式
	public set factor(value: number) {
		this.player.x = (1-value)*(1-value) * this.player.x + 
		2 * value * (1-value)*(this.player.x + this.targetPos.x) / 2 + value * value * (this.targetPos.x);

		this.player.y = (1-value)*(1-value) * this.player.y + 
		2 * value * (1-value)*(this.player.y - 300) / 2 + value * value * (this.targetPos.y);
	}

}